#include "mainwindow.h"
#include "networkdebugging.h"
#include "ui_networkdebugging.h"

#include <QTcpSocket>
#include <QNetworkInterface>
#include <QMessageBox>
#include <QFileDialog>
#include <QTcpServer>
#include <QUdpSocket>  // 新增UDP支持
#include <QDataStream>  // 用于二进制数据处理
#include <QSerialPortInfo>
#include <QTcpServer>
#include <QPainter>
//#include <QSerialPort>



networkDebugging::networkDebugging(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::networkDebugging),
    serialPort(nullptr)  // 初始化串口指针为null
{

    ui->setupUi(this);


    connect(ui->Last,&QPushButton::clicked,[=]{
        //发一个信号过去
        emit this->back();
    });

    //serialStatus1  =false;
    server = new QTcpServer(this);
   // udpListener = new QUdpSocket(this);
    //udpSocket = new QUdpSocket(this);  // 初始化UDP套接字
    //bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) 8888--15000
    /*
    QHostAddress addr("192.168.1.126");
    if(!server->listen(addr,8888))
    {
        qDebug() << "listenError";
        return;
    }*/

    connect(server,SIGNAL(newConnection()),this,SLOT(on_newClient_connect()));


    ui->btnLineout->setEnabled(false);
    ui->btnStopListen->setEnabled(false);

    //connect(server,&QTcpServer::readyRead,this,&::networkDebugging::on_readyRead_handler);

    QList<QHostAddress> addresss = QNetworkInterface::allAddresses();
    for(QHostAddress tmp : addresss)
    {
        if(tmp.protocol() == QAbstractSocket::IPv4Protocol)
        {
            ui->comboBoxAddr->addItem(tmp.toString());
        }
    }
    //udpSocket = new QUdpSocket(this);
    //initUdpListener();  // 启动UDP监听，绑定8888端口

    //添加UDP数据接收处理
    //connect(udpSocket, &QUdpSocket::readyRead, this, &networkDebugging::onUdpDataReady);

}

networkDebugging::~networkDebugging()
{
    delete ui;
    //delete udpSocket;
}



// 实现设置串口指针的函数
void networkDebugging::setSerialPort(QSerialPort *serial)
{
    serialPort = serial;  // 接收主窗口传递的串口指针
}


void networkDebugging::on_newClient_connect()
{
    //qDebug() << "newClient In!";
    //bool QTcpServer::hasPendingConnections() const

    if(server->hasPendingConnections())
    {
        //QTcpSocket *QTcpServer::nextPendingConnection()
        QTcpSocket *connction = server->nextPendingConnection();
        qDebug() << "client Addr: " << connction->peerAddress().toString() << "port:" << connction->peerPort();
       /*ui->textEditRec->insertPlainText("客户端地址是:"+connction->peerAddress().toString()+
                                         "\n客户端端口号:"+QString::number(connction->peerPort()) +"\n");*/

        connect(connction,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler()));

        //void QAbstractSocket::disconnected()
        // connect(connction,SIGNAL(disconnected()),this,SLOT(mdisconnected()));
        //void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)
        connect(connction,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
                this,SLOT(mstateChanged(QAbstractSocket::SocketState)));
}
}

void networkDebugging::on_readyRead_handler()
{
    QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());

    QByteArray revData = tmpSock->readAll();
    ui->textEditRec->insertPlainText(revData+"\n");

}

void networkDebugging::mdisconnect()
{
    QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
    qDebug() << "client out!";
    QMessageBox msgBox;
    msgBox.setWindowTitle("连接断开");
    msgBox.setText("客户端断开！");
    msgBox.exec();
    //ui->textEditRec->insertPlainText("客户端断开！");
    tmpSock->deleteLater();
}

void networkDebugging::mstateChanged(QAbstractSocket::SocketState socketState)
{
    qDebug() << "client out In state:" << socketState;
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState://断开
        // 显示客户端断开的消息框
        QMessageBox::information(this, "连接状态", "客户端断开！");
        break;
    case QAbstractSocket::ConnectedState://连接成功
        // 显示客户端接入的消息框
        QMessageBox::information(this, "连接状态", "客户端接入！");
        break;
        // 移除了ConnectingState的处理，因为连接中通常不需要弹窗提示
    }
}


void networkDebugging::on_btnListen_clicked()
{
    //bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) 8888--15000
    //QHostAddress addr("192.168.1.126");
    int port = ui->lineEditPort->text().toInt();
    //if(!server->listen(QHostAddress::Any,port))
    if(!server->listen(QHostAddress(ui->comboBoxAddr->currentText()),port))
    {
        qDebug() << "listenError";
        QMessageBox msgBox;
        msgBox.setWindowTitle("监听失败");
        msgBox.setText("端口号被占用");
        msgBox.exec();
        return;
    }
    ui->btnListen->setEnabled(false);
    ui->btnLineout->setEnabled(true);
    ui->btnStopListen->setEnabled(true);
}


void networkDebugging::on_btnSaveText_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save Network Data"),
                                                    "G:/qt/project/gpsserialport/network_position.txt",
                                                    tr("Text (*.txt);"));
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            QMessageBox::warning(this, tr("保存失败"), tr("无法打开文件进行写入"));
            return;
        }

        QTextStream out(&file);
        // 保存接收区和解析区的内容
        out << "=== 原始网络数据 ===\n";
        out << ui->textEditRec->toPlainText() << "\n\n";
        out << "=== 解析结果 ===\n";
        out << ui->textEditText->toPlainText();
        file.close();

        QMessageBox::information(this, tr("保存成功"), tr("数据已成功保存到文件"));
    }
}


void networkDebugging::on_solve_clicked()
{
    // 1. 获取需要解析的数据
    QByteArray NetworkData = ui->textEditRec->toPlainText().toUtf8();

    // 2. 检查数据是否为空
    if (NetworkData.isEmpty())
    {
        ui->textEditText->append("没有可解析的数据，请先接收数据或输入内容");
        return;
    }

    // 3. 调用解析函数
    GpsData parsedNetworkData = parseNetworkData(NetworkData);

    // 4. 处理解析结果
    if (parsedNetworkData.longitude != 0 || parsedNetworkData.latitude != 0)
    {
        // 解析成功，合并信息并更新UI显示
        QString info = QString("解析成功:\n 经度: %1\n 纬度: %2\n 时间: %3")
                           .arg(parsedNetworkData.longitude, 0, 'f', 5)
                           .arg(parsedNetworkData.latitude, 0, 'f', 5)
                           .arg(parsedNetworkData.time.toString("yyyy-MM-dd hh:mm:ss"));

        ui->textEditText->setText(info);
        //ui->textEditSendContext->setText(info);
    }
    else
    {
        // 解析失败，进行提示
        ui->textEditText->append("解析失败，请检查数据格式");
    }
}

// 解析串口接收到的经纬度数据
GpsData networkDebugging::parseNetworkData(const QByteArray &data)
{
    GpsData result = {0, 0, QDateTime::currentDateTime(), false};
    QString dataStr = QString::fromUtf8(data);

    // 1. 验证数据格式
    if (!dataStr.startsWith("$AE,") && !dataStr.endsWith("\r\n"))
    {
        qDebug() << "格式错误：起始或结束标志不正确";
        return result;
    }

    // 2. 提取中间有效数据（改进部分）
    // 先去除首尾的固定字符，再处理可能的控制字符
    QString content = dataStr.mid(4); // 去除前缀"$AE,"
    content = content.left(content.length() - 6); // 去除末尾"\r\n"
    content = content.trimmed(); // 确保没有残留的空白字符

    // 3. 分割经纬度数据
    QStringList parts = content.split(",");
    if (parts.size() != 2) {
        qDebug() << "格式错误：经纬度分割后数量不正确，实际为" << parts.size();
        return result;
    }

    // 4. 转换为数值类型（增加调试信息）
    bool lonOk, latOk;
    double longitude = parts[0].toDouble(&lonOk);
    double latitude = parts[1].toDouble(&latOk);

    // 输出调试信息，查看实际处理的字符串
    qDebug() << "处理的经度字符串:" << parts[0];
    qDebug() << "处理的纬度字符串:" << parts[1];

    // 5. 验证经纬度有效性
    if (!lonOk) {
        qDebug() << "转换错误：经度不是有效数字 -" << parts[0];
        return result;
    }
    if (!latOk) {
        qDebug() << "转换错误：纬度不是有效数字 -" << parts[1];
        return result;
    }

    // 6. 验证经纬度范围
    if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) {
        qDebug() << "范围错误：经纬度超出有效范围";
        return result;
    }

    // 所有验证通过
    result.longitude = longitude;
    result.latitude = latitude;
    result.time = QDateTime::currentDateTime();
    result.isValid = true;

    // 在解析成功后添加代码更新UI
    if (result.isValid)
    {
        // 将解析得到的经纬度显示到对应的输入框
        ui->lineEdit_latitude->setText(QString::number(result.latitude, 'f', 6));
        ui->lineEdit_longtitude->setText(QString::number(result.longitude, 'f', 6));

        // 由于数据来自串口解析，而非用户输入，可禁用输入框避免手动修改
        ui->lineEdit_latitude->setReadOnly(true);
        ui->lineEdit_longtitude->setReadOnly(true);
    }

    return result;
}


void networkDebugging::on_btnSend_clicked()
{
    QList<QTcpSocket*> tcpSocketClients =  server->findChildren<QTcpSocket*>();

    for(QTcpSocket* tmp:tcpSocketClients)
    {

        tmp->write(ui->textEditSendContext->toPlainText().toStdString().c_str());
    }
}


void networkDebugging::on_ClearImput_clicked()
{
    ui->textEditSendContext->setText("");
}


void networkDebugging::on_btnStopListen_clicked()
{

    server->close();
    ui->btnListen->setEnabled(true);
    ui->btnLineout->setEnabled(false);
    ui->btnStopListen->setEnabled(false);
}


void networkDebugging::on_btnLineout_clicked()
{
    on_btnStopListen_clicked();
    delete server;
    this->close();

}
/*
// 新增：以ASCII码形式组包并发送GPS数据
void networkDebugging::sendGpsDataAsAscii(const GpsData &data, bool isTcp)
{
    if (!data.isValid)
    {
        QMessageBox::warning(this, "发送失败", "GPS数据无效，无法发送");
        return;
    }

    // 1. 构建ASCII格式数据包
    // 格式：$GPGGA,经度,纬度,时间*校验和\r\n（模拟NMEA格式，便于ASCII传输）
    QString asciiData = QString("$GPGGA,%1,%2,%3*%4\r\n")
                            .arg(data.longitude, 0, 'f', 6)  // 经度，保留6位小数
                            .arg(data.latitude, 0, 'f', 6)   // 纬度，保留6位小数
                            .arg(data.time.toString("HHmmss.zzz"));   // 时间，格式：时分秒.毫秒

    QByteArray packet = asciiData.toUtf8();  // 转换为ASCII兼容的UTF-8（纯ASCII字符）

    // 2. 显示发送的ASCII数据包内容
    QString packetInfo = QString("发送的ASCII数据包详情：\n") +
                         QString("总长度：%1字节\n").arg(packet.size()) +
                         QString("ASCII内容：%1\n").arg(asciiData);
    //ui->textEditRec->append(packetInfo);
    qDebug() << packetInfo;

    // 3. 发送数据（与原逻辑一致，只是数据包为ASCII格式）
    QString targetIp = getTargetIp();
    quint16 targetPort = getTargetPort();

    if (targetIp.isEmpty() || targetPort == 0)
    {
        QMessageBox::warning(this, "参数错误", "请输入正确的目标IP和端口");
        return;
    }

    if (isTcp)
    {
        // TCP发送ASCII数据
        QList<QTcpSocket*> clients = server->findChildren<QTcpSocket*>();
        foreach (QTcpSocket *client, clients)
        {
            if (client->state() == QAbstractSocket::ConnectedState)
            {
                client->write(packet);
                client->flush();
            }
        }
        //ui->textEditRec->append("TCP ASCII发送成功，长度：" + QString::number(packet.size()));
        qDebug() << "TCP ASCII发送成功，长度：" + QString::number(packet.size());

    }
    else
    {
        // UDP发送ASCII数据
        QHostAddress targetAddr(targetIp);
        udpSocket->writeDatagram(packet, targetAddr, targetPort);
        //ui->textEditRec->append("UDP ASCII发送成功，长度：" + QString::number(packet.size()));
        qDebug() << "UDP ASCII发送成功，长度：" + QString::number(packet.size());
    }
}

// 辅助函数：计算简单校验和（用于ASCII数据包）
quint8 calculateChecksum(const QString &data)
{
    quint8 checksum = 0;
    // 从$后开始计算，到*前结束（NMEA标准）
    int start = data.indexOf('$') + 1;
    int end = data.indexOf('*');
    if (start < 0 || end < 0 || start >= end)
        return checksum;

    for (int i = start; i < end; ++i)
    {
        checksum ^= data.at(i).toLatin1();  // 异或校验
    }
    return checksum;
}*/


//新增：获取目标IP
QString networkDebugging::getTargetIp()
{
    return ui->lineEdit_IP->text().trimmed();  // 假设UI有目标IP输入框
}

//新增：获取目标端口
quint16 networkDebugging::getTargetPort()
{
    return ui->lineEdit_Com->text().toUInt();  // 假设UI有目标端口输入框
}


void networkDebugging::on_ClearRec_clicked()
{
    ui->textEditRec->setText("");
}


void networkDebugging::on_SendExternallyUDP_clicked()
{
/*
    // 解析当前显示的GPS数据并发送
    QByteArray data = ui->textEditRec->toPlainText().toUtf8();
    qDebug() << "解析数据";
    qDebug() << data;
    GpsData gps = parseNetworkData(data);
    sendGpsData(gps, false);
*/
    // 从解析结果文本框提取内容，而非接收文本框
    QString parsedText = ui->textEditText->toPlainText();
    qDebug() << "解析数据";
    qDebug() << parsedText;
    GpsData gps = parseDisplayedGps(parsedText);
    sendGpsDataAsBinary(gps, true);
}


void networkDebugging::on_SendExternallyTCP_clicked()
{
    /*
    // 解析当前显示的GPS数据并发送
    QByteArray data = ui->textEditRec->toPlainText().toUtf8();
    qDebug() << "解析数据";
    qDebug() << data;
    GpsData gps = parseNetworkData(data);
    sendGpsData(gps, true);*/
    // 从解析结果文本框提取内容，而非接收文本框
    QString parsedText = ui->textEditText->toPlainText();
    //parseNetworkData
    qDebug() << "解析数据";
    qDebug() << parsedText;
    GpsData gps = parseDisplayedGps(parsedText);
    sendGpsDataAsBinary(gps, false);

}

GpsData networkDebugging::parseDisplayedGps(const QString &text)
{
    GpsData gps = {0, 0, QDateTime(), false};
    /*
    //打印待解析的原始文本
    qDebug() << "待解析文本内容：" << text;
    qDebug() << "文本长度：" << text.length();*/
    // 移除文本中可能存在的"解析成功："前缀（包括中英文冒号和前后空格）
    QString processedText = text;
    processedText.remove(QRegularExpression(R"(\s*解析成功[:：]\s*)"));
    //qDebug() << "待解析文本内容：" << text;
    qDebug() << "待解析文本内容：" << processedText;

    // 1. 定义正则表达式（支持正负经纬度）
    QRegularExpression rx("经度: (-?\\d+\\.\\d+)\n\\s*纬度: (-?\\d+\\.\\d+)\n\\s*时间: (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})");

    // 2. 执行匹配
    QRegularExpressionMatch match = rx.match(processedText);
    if (!match.hasMatch())
    {
        qDebug() << "解析失败：文本格式不匹配，预期格式：\n经度: [±数字]\n纬度: [±数字]\n时间: yyyy-MM-dd hh:mm:ss";
        return gps;
    }

    // 3. 解析经度（带有效性检查）
    bool lonOk;
    double longitude = match.captured(1).toDouble(&lonOk);
    if (!lonOk || longitude < -180 || longitude > 180) {
        qDebug() << "经度无效：" << match.captured(1);
        return gps;
    }

    // 4. 解析纬度（带有效性检查）
    bool latOk;
    double latitude = match.captured(2).toDouble(&latOk);
    if (!latOk || latitude < -90 || latitude > 90) {
        qDebug() << "纬度无效：" << match.captured(2);
        return gps;
    }

    // 5. 解析时间（带有效性检查）
    QDateTime time = QDateTime::fromString(match.captured(3), "yyyy-MM-dd hh:mm:ss");
    if (!time.isValid())
    {
        qDebug() << "时间格式无效：" << match.captured(3);
        return gps;
    }

    // 6. 赋值并标记为有效
    gps.longitude = longitude;
    gps.latitude = latitude;
    gps.time = time;
    gps.isValid = true;

    return gps;


}


/*
// 添加UDP数据接收处理函数
void networkDebugging::onUdpDataReady()
{
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;
        udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);

        // 显示接收到的ASCII数据
        ui->textEditRec->append(QString("UDP接收来自 %1:%2 的数据:\n%3\n")
                                    .arg(sender.toString())
                                    .arg(senderPort)
                                    .arg(QString::fromUtf8(datagram)));  // 以ASCII形式解析
    }
}*/




// 新增：将二进制数据转换为01字符串
QString networkDebugging::binaryToBitString(const QByteArray &binaryData) {
    QString bitString;
    for (char c : binaryData) {
        for (int i = 7; i >= 0; --i) {
            bitString += (c & (1 << i)) ? '1' : '0';
        }
        bitString += ' '; // 字节之间添加空格分隔
    }
    return bitString.trimmed(); // 移除末尾的空格
}

// 新增：以二进制格式组包并发送GPS数据
void networkDebugging::sendGpsDataAsBinary(const GpsData &data, bool isTcp)
{
    if (!data.isValid)
    {
        QMessageBox::warning(this, "发送失败", "GPS数据无效，无法发送");
        return;
    }

    // 1. 二进制数据包格式定义（共24字节）：
    // - 帧头：2字节（固定为0xAA55）
    // - 经度：8字节（double类型，小端模式）
    // - 纬度：8字节（double类型，小端模式）
    // - 时间戳：4字节（UTC时间戳，从1970-01-01 00:00:00开始的秒数）
    // - 校验和：2字节（前22字节的CRC16校验）

    QByteArray packet;
    QDataStream stream(&packet, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::LittleEndian); // 设置小端模式

    // 2. 写入帧头
    quint16 header = 0xAA55;
    stream << header;

    // 3. 写入经纬度（double类型）
    stream << data.longitude;
    stream << data.latitude;

    // 4. 写入时间戳（UTC秒数）
    quint32 timestamp = data.time.toSecsSinceEpoch();
    stream << timestamp;

    // 5. 计算CRC16校验和（前22字节）
    quint16 crc = calculateCrc16(packet);
    stream << crc;

    // 6. 显示发送的二进制数据包详情
    QString packetInfo = QString("发送的二进制数据包详情：\n") +
                         QString("总长度：%1字节\n").arg(packet.size()) +
                         QString("帧头：0x%1\n").arg(header, 4, 16, QLatin1Char('0')) +
                         QString("经度：%1\n").arg(data.longitude) +
                         QString("纬度：%1\n").arg(data.latitude) +
                         QString("时间戳：%1\n").arg(timestamp) +
                         QString("校验和：0x%1").arg(crc, 4, 16, QLatin1Char('0'));
    qDebug() << packetInfo;
    // 新增：打印完整的二进制数据包（十六进制形式）
    qDebug() << "二进制数据内容（十六进制）：" << packet.toHex(' ').toUpper();
    // 新增：打印完整的二进制数据包（二进制位形式）
    qDebug() << "二进制数据内容（二进制）：" << binaryToBitString(packet);

    // 7. 发送数据
    QString targetIp = getTargetIp();
    quint16 targetPort = getTargetPort();

    if (targetIp.isEmpty() || targetPort == 0)
    {
        QMessageBox::warning(this, "参数错误", "请输入正确的目标IP和端口");
        return;
    }

    if (isTcp)
    {
        // TCP发送二进制数据
        QList<QTcpSocket*> clients = server->findChildren<QTcpSocket*>();
        foreach (QTcpSocket *client, clients)
        {
            if (client->state() == QAbstractSocket::ConnectedState)
            {
                client->write(packet);
                client->flush();
            }
        }
        qDebug() << "TCP二进制发送成功，长度：" + QString::number(packet.size());
    }
    else
    {
        // UDP发送二进制数据
        QHostAddress targetAddr(targetIp);
        udpSocket->writeDatagram(packet, targetAddr, targetPort);
        qDebug() << "UDP二进制发送成功，长度：" + QString::number(packet.size());
    }
}

// 新增：CRC16校验和计算（用于二进制数据包）
quint16 networkDebugging::calculateCrc16(const QByteArray &data)
{
    quint16 crc = 0xFFFF; // 初始值
    const quint16 polynomial = 0x8005; // 多项式

    for (int i = 0; i < data.size(); ++i)
    {
        crc ^= static_cast<quint8>(data[i]) << 8;
        for (int j = 0; j < 8; ++j)
        {
            if (crc & 0x8000)
                crc = (crc << 1) ^ polynomial;
            else
                crc <<= 1;
        }
    }
    return crc;
}


void networkDebugging::on_SendContextToCom_clicked()
{
    // 1. 获取网口接收的文本数据
    QString text = ui->textEditRec->toPlainText();
    if (text.isEmpty()) {
        qDebug() << "网口接收区无数据，无法转发";
        QMessageBox::warning(this, "转发失败", "网口接收区没有数据可转发");
        return;
    }

    // 2. 转换数据格式并记录时间
    QByteArray serverData = text.toUtf8();  // 转换为UTF-8字节数组
    QString timeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");

    // 3. 调试信息：显示待转发数据
    qDebug() << QString("[%1] 准备转发到串口的数据: %2")
                    .arg(timeStr)
                    .arg(text);

    // 4. 检查串口是否有效且已打开 - 改进版本
    MainWindow *mainWin = nullptr;

    // 尝试多种方式获取主窗口指针
    if (parentWidget()) {
        mainWin = qobject_cast<MainWindow*>(parentWidget());
    }
    // 如果父窗口不是主窗口，尝试查找应用程序中的主窗口
    if (!mainWin) {
        foreach (QWidget *widget, QApplication::topLevelWidgets()) {
            mainWin = qobject_cast<MainWindow*>(widget);
            if (mainWin) break;
        }
    }

    // 直接通过主窗口检查串口状态
    if (!mainWin) {
        qDebug() << QString("[%1] 错误：无法获取主窗口实例").arg(timeStr);
        QMessageBox::warning(this, "转发失败", "无法连接到主窗口，请重启应用");
        return;
    }

    // 新增：通过主窗口方法直接检查串口是否打开
    if (!mainWin->isSerialPortOpen()) {
        qDebug() << QString("[%1] 错误：串口未打开（主窗口报告）").arg(timeStr);
        QMessageBox::warning(this, "转发失败", "串口未打开，请先在主窗口打开串口");
        return;
    }

    // 从主窗口获取串口指针
    serialPort = mainWin->getSerialPort();
    if (!serialPort) {
        qDebug() << QString("[%1] 错误：未获取到串口对象").arg(timeStr);
        QMessageBox::warning(this, "转发失败", "未初始化串口，请先在主窗口打开串口");
        return;
    }

    // 再次双重检查
    if (!serialPort->isOpen()) {
        qDebug() << QString("[%1] 错误：串口对象报告未打开").arg(timeStr);
        QMessageBox::warning(this, "转发失败", "串口未打开，请先在主窗口打开串口");
        return;
    }

    // 5. 发送数据到串口
    qint64 bytesWritten = serialPort->write(serverData);

    if (bytesWritten == -1) {
        // 发送失败：显示错误信息
        QString errorMsg = QString("串口发送失败: %1").arg(serialPort->errorString());
        qDebug() << QString("[%1] %2").arg(timeStr).arg(errorMsg);
        ui->textEditRec->append(QString("[%1] 错误：%2").arg(timeStr).arg(errorMsg));
    } else {
        // 发送成功：显示成功信息
        QString successMsg = QString("已转发到串口，长度: %1字节").arg(bytesWritten);
        qDebug() << QString("[%1] %2").arg(timeStr).arg(successMsg);

        // 6. 在主窗口的接收区显示转发的数据
        mainWin->appendTotextEditRev(text);
    }
}


// 以下是目标网口界面的接收处理逻辑（通常在另一个类或窗口中实现）
// 目标网口界面类：NetInterfaceWindow.cpp
void networkDebugging::initUdpListener()
{
    // 初始化UDP监听，端口必须与发送端的targetPort一致
    quint16 listenPort =8888;
    if (udpListener->bind(QHostAddress::Any, listenPort))
    {
        // 绑定成功，连接接收信号
        connect(udpListener, &QUdpSocket::readyRead,
                this, &networkDebugging::onUdpDataReceived);
       qDebug () << "[初始化] 目标网口已启动监听，端口: " + QString::number(listenPort);
    } else
    {
        qDebug () <<"[错误] 目标网口监听失败: " + udpListener->errorString();
    }
}

// 目标网口界面接收数据并显示
void networkDebugging::onUdpDataReceived()
{
    while (udpListener->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpListener->pendingDatagramSize());

        QHostAddress senderIp;
        quint16 senderPort;
        udpListener->readDatagram(datagram.data(), datagram.size(), &senderIp, &senderPort);

        // 在目标网口的接收区域显示数据
        QString timeStr = QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss] ");
        qDebug () << timeStr + "收到来自 " + senderIp.toString() +
                                    ":" + QString::number(senderPort) + " 的数据:";
        ui->textEditRec->append(datagram); // 显示接收到的内容

        /*
        // 自动滚动到底部
        ui->textEditNetRecv->verticalScrollBar()->setValue(
            ui->textEditNetRecv->verticalScrollBar()->maximum()
            );*/
    }
}

void networkDebugging::on_AddPoint_clicked()
{
    // 获取经纬度输入
    double latitude = ui->lineEdit_latitude->text().toDouble();
    double longitude = ui->lineEdit_longtitude->text().toDouble();

    // 添加到坐标列表
    coordinates.append(QPointF(latitude, longitude));

    // 更新显示
    update();

    // 状态栏显示
    statusBar()->showMessage(QString("添加点: 纬度 = %1, 经度 = %2").arg(latitude).arg(longitude), 3000);
}


void networkDebugging::on_ClearPoint_clicked()
{
    // 清空坐标列表
    coordinates.clear();

    // 更新显示
    update();

    // 状态栏显示
    statusBar()->showMessage("已清除所有点", 2000);
}


QPointF networkDebugging::latLngToScreen(const QPointF &latLng)
{
    QRect drawArea = ui->frame->geometry();
    drawArea.moveTopLeft(ui->frame->mapToGlobal(QPoint(0, 0)));
    drawArea = drawArea.translated(-this->geometry().topLeft());

    // 调整边界，留出一些边距
    drawArea.adjust(10, 10, -10, -10);

    double x = drawArea.left() +
               (latLng.y() - minLongitude) * drawArea.width() / (maxLongitude - minLongitude);
    double y = drawArea.bottom() -
               (latLng.x() - minLatitude) * drawArea.height() / (maxLatitude - minLatitude);

    return QPointF(x, y);
}



void networkDebugging::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 获取绘图区域
    QRect drawArea = ui->frame->geometry();
    drawArea.moveTopLeft(ui->frame->mapToGlobal(QPoint(0, 0)));
    drawArea = drawArea.translated(-this->geometry().topLeft());

    // 绘制背景
    //painter.fillRect(drawArea, Qt::white);

    // 绘制网格和坐标轴
    painter.setPen(QPen(Qt::lightGray, 1));

    // 计算网格间距
    int gridCount = 5;
    int gridWidth = drawArea.width() / gridCount;
    int gridHeight = drawArea.height() / gridCount;

    // 绘制垂直线
    for (int i = 0; i <= gridCount; ++i) {
        int x = drawArea.left() + i * gridWidth;
        painter.drawLine(x, drawArea.top(), x, drawArea.bottom());

        // 绘制经度标签
        double longitude = minLongitude + (maxLongitude - minLongitude) * i / gridCount;
        painter.drawText(x -20, drawArea.bottom() + 20, QString::number(longitude, 'f', 2));
    }

    // 绘制水平线
    for (int i = 0; i <= gridCount; ++i) {
        int y = drawArea.top() + i * gridHeight;
        painter.drawLine(drawArea.left(), y, drawArea.right(), y);

        // 绘制纬度标签
        double latitude = maxLatitude - (maxLatitude - minLatitude) * i / gridCount;
        painter.drawText(drawArea.left() - 40, y + 5, QString::number(latitude, 'f', 2));
    }

    // 绘制坐标轴
    painter.setPen(QPen(Qt::black, 2));
    painter.drawLine(drawArea.left(), drawArea.top(), drawArea.left(), drawArea.bottom());  // Y轴
    painter.drawLine(drawArea.left(), drawArea.bottom(), drawArea.right(), drawArea.bottom());  // X轴

    // 绘制所有坐标点
    painter.setPen(QPen(Qt::red, 5, Qt::SolidLine, Qt::RoundCap));
    for (const auto &coord : coordinates) {
        QPointF screenPos = latLngToScreen(coord);
        painter.drawPoint(screenPos);
    }

    // 绘制图例
    painter.setPen(QPen(Qt::black, 1));
    painter.drawText(drawArea.left()-30 , drawArea.top() - 10, "经度范围: " +
                                                                    QString::number(minLongitude, 'f', 2) + " - " +
                                                                    QString::number(maxLongitude, 'f', 2));
    painter.drawText(drawArea.left() + 140, drawArea.top() - 10, "纬度范围: " +
                                                                     QString::number(minLatitude, 'f', 2) + " - " +
                                                                     QString::number(maxLatitude, 'f', 2));
}


